package com.ken.controller;

import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

/**
 * Created by renchongyu on 2018/12/1.
 */
@RestController
public class InderController {

    @Autowired
    private TransportClient client;

    @GetMapping("/")
    public String index(){
        return "index";
    }


    /**
     * 查询缓存
     * @param id
     * @return
     */
    @GetMapping("/get/book/novel")
    @ResponseBody
    public ResponseEntity get(@RequestParam(name = "id",defaultValue = "") String id){
        if(StringUtils.isEmpty(id)){
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }
        GetResponse response = this.client.prepareGet("book","novel",id).get();
        if(!response.isExists()){
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }
        System.out.println(response.getSource());
        return new ResponseEntity(response.getSource(), HttpStatus.OK);
    }

    /**
     * 增加缓存
     * @param title
     * @param author
     * @param wordCount
     * @param publishDate
     * @return
     */
    @PostMapping("add/book/novel")
    @ResponseBody
    public ResponseEntity add(@RequestParam(name = "title",defaultValue = "")String title,
                              @RequestParam(name = "author",defaultValue = "")String author,
                              @RequestParam(name = "word_count",defaultValue = "0")int wordCount,
                              @RequestParam(name = "publish_date")@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date publishDate){

        try {
            XContentBuilder content = XContentFactory.jsonBuilder()
                    .startObject()
                    .field("title",title)
                    .field("author",author)
                    .field("word_count",wordCount)
                    .field("publish_date",publishDate.getTime())
                    .endObject();
            IndexResponse result = this.client.prepareIndex("book","novel")
                    .setSource(content)
                    .get();
            return new ResponseEntity(result.getId(), HttpStatus.OK);
        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
        }

    }

    /**
     * 删除缓存
     * @param id
     * @return
     */
    @GetMapping("/delete/book/novel")
    @ResponseBody
    public ResponseEntity delete(@RequestParam(name = "id",defaultValue = "") String id){
        if(StringUtils.isEmpty(id)){
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }
        DeleteResponse response = this.client.prepareDelete("book","novel",id).get();
        return new ResponseEntity(response.getResult(),HttpStatus.OK);
    }

    /**
     * 更新缓存
     * @param id
     * @param title
     * @param author
     * @param wordCount
     * @param publishDate
     * @return
     */
    @PutMapping("/update/book/novel")
    @ResponseBody
    public ResponseEntity update(@RequestParam(name = "id")String id,
                                 @RequestParam(name = "title",required = false) String title,
                                 @RequestParam(name = "author",required = false) String author,
                                 @RequestParam(name = "word_count",required = false)int wordCount,
                                 @RequestParam(name = "publish_date",required = false)@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date publishDate){
        UpdateRequest ur = new UpdateRequest("book","novel",id);

        try {
            XContentBuilder builder = XContentFactory.jsonBuilder()
                    .startObject();
            if (title!=null){
                builder.field("title",title);
            }
            if (author!=null){
                builder.field("author",author);
            }
            if(wordCount!=0){
                builder.field("word_count",wordCount);
            }
            if (publishDate!=null){
                builder.field("publish_date",publishDate.getTime());
            }
            builder.endObject();
            ur.doc(builder);
        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
        }

        try {
            UpdateResponse result = this.client.update(ur).get();
            return new ResponseEntity(result.getId(),HttpStatus.OK);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
            return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
        }
        return null;
    }

    /**
     * 复合查询
     * @param author
     * @param title
     * @param gtWordCount
     * @param ltWordCount
     * @return
     */
    @PostMapping("query/book/novel")
    @ResponseBody
    public ResponseEntity query(@RequestParam(name = "author",required = false)String author,
                                @RequestParam(name = "title",required = false)String title,
                                @RequestParam(name = "gt_word_count",defaultValue = "0")int gtWordCount,
                                @RequestParam(name = "lt_word_count",required = false)Integer ltWordCount){
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        if(author!=null){
            boolQuery.must(QueryBuilders.matchQuery("author",author));
        }
        if(title!=null){
            boolQuery.must(QueryBuilders.matchQuery("title",title));
        }
        RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("word_count")
                .from(gtWordCount);
        if (ltWordCount!=null && ltWordCount>0){
            rangeQuery.to(ltWordCount);
        }
        //这句是关键，没有时间段查询将不生效
        boolQuery.filter(rangeQuery);
        SearchRequestBuilder searchRequest = this.client.prepareSearch("book")
                .setTypes("novel")
                .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)//如果条数多用QUERY_THEN_FETCH
                .setQuery(boolQuery)
                .setFrom(0)
                .setSize(10);
        SearchResponse response = searchRequest.get();
        List<Map<String,Object>> result = new ArrayList<Map<String,Object>>();
        for (SearchHit hit:response.getHits()){
            result.add(hit.getSource());
        }
        return new ResponseEntity(result,HttpStatus.OK);
    }
}
